package com.udream.support.alipay;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeCancelModel;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayDataBillDownloadurlGetRequest;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeCancelRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayDataBillDownloadurlGetResponse;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.udream.support.LogUtils;

/**
 * 生成APP支付宝支付报文工具
 */
@Component
public class AliPayService {
 
 /**
  * 商户appid
  */
 @Value("${alipay.appid}")
 private String appid;
 
 /**
  * 私钥 pkcs8格式的
  */
 @Value("${alipay.rsa_private_key}")
 private String rsa_private_key;
 
 /**
  * 服务器异步通知页面路径 需http://或者https://格式的完整路径， 不能加?id=123这类自定义参数， 必须外网可以正常访问
  */
 @Value("${alipay.online.notify_url}")
 private String notify_url;
 
 @Value("${alipay.offline.notify_url}")
 private String offline_notify_url;
 
 @Value("${alipay.qrcode.notify_url}")
 private String qrCode_notify_url;
 
 /**
  * 页面跳转同步通知页面路径 需http://或者https://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问
  */
 @Value("${alipay.return_url}")
 private String return_url;
 
 /**
  * 请求网关地址
  */
 @Value("${alipay.url}")
 private String url;
 
 /**
  * 编码
  */
 @Value("${alipay.charset}")
 private String charset = "UTF-8";
 
 /**
  * 返回格式
  */
 @Value("${alipay.format}")
 private String format = "json";
 
 /**
  * 支付宝公钥
  */
 @Value("${alipay.alipay_public_key}")
 private String alipay_public_key;
 
 /**
  * 日志记录目录
  */
 @Value("${alipay.log_path}")
 private String log_path;
 
 /**
  * 签名类型
  */
 @Value("${alipay.signtype}")
 private String signtype = "RSA2";
 
 /**
  * 默认超时时间
  */
 @Value("${alipay.timeout_express}")
 private String timeout_express = "2m";
 
 /**
  * 销售产品码，商家和支付宝签约的产品码，为固定值QUICK_MSECURITY_PAY
  */
 @Value("${alipay.product_code}")
 private String product_code = "QUICK_MSECURITY_PAY";
 
 /**
  * 时间戳
  */
 private String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
 
 /**
  * 封装支付宝App支付报文
  *
  * @param request
  * @return
  * @throws AlipayApiException
  */
 public synchronized String alipayApp(AppPayRequest request) throws AlipayApiException {
  AlipayClient alipayClient = new DefaultAlipayClient(this.getUrl(), this.getAppid(), this.getRsa_private_key(), this.getFormat(),
   this.getCharset(), this.getAlipay_public_key(), this.getSigntype());
  AlipayTradeAppPayRequest payRequest = new AlipayTradeAppPayRequest();
  // 区分不同的回调地址，隔离处理回调
  if (request.getPassBackParams().trim().equals("online")) {
   payRequest.setNotifyUrl(this.getNotify_url());
  }
  if (request.getPassBackParams().trim().equals("offline")) {
   payRequest.setNotifyUrl(this.getOffline_notify_url());
  }
  payRequest.setReturnUrl(this.getReturn_url());
  AlipayTradeAppPayModel alipayTradeAppPayModel = new AlipayTradeAppPayModel();
  alipayTradeAppPayModel.setOutTradeNo(request.getTradNo());//商户订单号
  alipayTradeAppPayModel.setSubject(request.getSubject());//订单主体
  //订单总价
  /*alipayTradeAppPayModel
   .setTotalAmount(request.getTotalAmountString());*/
  alipayTradeAppPayModel.setTotalAmount("0.01");//测试阶段暂时所有订单都为1分钱
  //订单描述
  alipayTradeAppPayModel.setBody(request.getBody());
  //请求超时时间
  alipayTradeAppPayModel.setTimeoutExpress(this.getTimeout_express());
  //商户产品代码
  alipayTradeAppPayModel.setProductCode(this.getProduct_code());
  //公共回传参数
  alipayTradeAppPayModel.setPassbackParams(request.getPassBackParams());
  // 设置业务请求参数
  payRequest.setBizModel(alipayTradeAppPayModel);
  LogUtils.performance.info("请求支付宝APP支付请求bizContent:{}", request.toString());
  //生成App请求报文
  AlipayTradeAppPayResponse response = alipayClient.sdkExecute(payRequest);
  LogUtils.performance.info("请求支付宝当面付响应body:{}", response.getBody());
  return response.getBody();
 }
 
 /**
  * 创建收款二维码
  *
  * @param request
  * @return
  */
 public synchronized PrecreateQrCodeResponse alipayPrecreateQrCode(PrecreateQrCodeRequest request) throws AlipayApiException {
  AlipayClient alipayClient = new DefaultAlipayClient(this.getUrl(), this.getAppid(), this.getRsa_private_key(), this.getFormat(),
   this.getCharset(), this.getAlipay_public_key(), this.getSigntype());
  AlipayTradePrecreateRequest alipayTradePrecreateRequest = new AlipayTradePrecreateRequest();
  alipayTradePrecreateRequest.setNotifyUrl(qrCode_notify_url);
  AlipayTradePrecreateModel bizModel = new AlipayTradePrecreateModel();
  bizModel.setOutTradeNo(request.getOut_trade_no());
  bizModel.setSubject(request.getSubject());
  bizModel.setBody(request.getBody());
//  bizModel.setTotalAmount(request.getTotal_amount());
  bizModel.setTotalAmount("0.01");//测试阶段暂时设置为所有订单都为1分钱
  alipayTradePrecreateRequest.setBizModel(bizModel);
  LogUtils.performance.info("请求支付宝当面付请求bizContent:{}", request.toString());
  AlipayTradePrecreateResponse alipayTradePrecreateResponse = alipayClient.execute(alipayTradePrecreateRequest);
  PrecreateQrCodeResponse response = new PrecreateQrCodeResponse();
  LogUtils.performance.info("请求支付宝当面付响应body:{}", alipayTradePrecreateResponse.getBody());
  if (alipayTradePrecreateResponse.isSuccess()) {
   response.setResult(true);
   response.setQrCode(alipayTradePrecreateResponse.getQrCode());
   response.setTradeNo(alipayTradePrecreateResponse.getOutTradeNo());
  } else {
   response.setResult(false);
  }
  response.setCode(alipayTradePrecreateResponse.getCode());
  response.setMsg(alipayTradePrecreateResponse.getMsg());
  response.setSubCode(alipayTradePrecreateResponse.getSubCode());
  response.setSubMsg(alipayTradePrecreateResponse.getSubMsg());
  return response;
 }
 
 /**
  * 取消支付订单
  *
  * @param request
  * @return
  */
 private synchronized boolean cancelPay(CancelPayRequest request) throws AlipayApiException {
  AlipayClient alipayClient = new DefaultAlipayClient(this.getUrl(), this.getAppid(), this.getRsa_private_key(), this.getFormat(),
   this.getCharset(), this.getAlipay_public_key(), this.getSigntype());
  AlipayTradeCancelRequest alipayTradeCancelRequest = new AlipayTradeCancelRequest();
  AlipayTradeCancelModel alipayTradeCancelModel = new AlipayTradeCancelModel();
  alipayTradeCancelModel.setOutTradeNo(request.getOut_trade_no());
  alipayTradeCancelModel.setTradeNo(request.getTrade_no());
  alipayTradeCancelRequest.setBizModel(alipayTradeCancelModel);
  AlipayTradeCancelResponse alipayTradeCancelResponse = alipayClient.execute(alipayTradeCancelRequest);
  if (alipayTradeCancelResponse.isSuccess()) {
   return true;
  }
  return false;
 }
 
 /**
  * 支付宝查询订单
  *
  * @param request
  * @return
  */
 public synchronized QueryTradeResponse queryTrade(QueryTradeRequest request) throws AlipayApiException {
  AlipayClient alipayClient = new DefaultAlipayClient(this.getUrl(), this.getAppid(), this.getRsa_private_key(), this.getFormat(),
   this.getCharset(), this.getAlipay_public_key(), this.getSigntype());
  AlipayTradeQueryRequest alipayTradeQueryRequest = new AlipayTradeQueryRequest();
  AlipayTradeQueryModel alipayTradeQueryModel = new AlipayTradeQueryModel();
  alipayTradeQueryModel.setOutTradeNo(request.getOut_trade_no());
//  alipayTradeQueryModel.setTradeNo(request.getTrade_no());
  alipayTradeQueryRequest.setBizModel(alipayTradeQueryModel);
  AlipayTradeQueryResponse alipayTradeQueryResponse = alipayClient.execute(alipayTradeQueryRequest);
  QueryTradeResponse response = new QueryTradeResponse();
  if (alipayTradeQueryResponse.isSuccess()) {
   response.setResult(true);
   response.setOutTradeNo(alipayTradeQueryResponse.getOutTradeNo());
   response.setTradeNo(alipayTradeQueryResponse.getTradeNo());
   response.setTotalAmout(alipayTradeQueryResponse.getTotalAmount());
   response.setTradeStatus(alipayTradeQueryResponse.getTradeStatus());
   response.setBuyerLoginId(alipayTradeQueryResponse.getBuyerLogonId());
   response.setSendPayDate(alipayTradeQueryResponse.getSendPayDate());
  } else {
   response.setResult(false);
  }
  response.setCode(alipayTradeQueryResponse.getCode());
  response.setMsg(alipayTradeQueryResponse.getMsg());
  response.setSubCode(alipayTradeQueryResponse.getSubCode());
  response.setSubMsg(alipayTradeQueryResponse.getSubMsg());
  return response;
 }
 
 /**
  * 支付宝退款接口
  *
  * @return
  */
 public synchronized RefundResponse alipayReFund(RefundRequest request) throws AlipayApiException {
  AlipayClient alipayClient = new DefaultAlipayClient(this.getUrl(), this.getAppid(), this.getRsa_private_key(), this.getFormat(),
   this.getCharset(), this.getAlipay_public_key(), this.getSigntype());
  AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
  String bizContent = JSON.toJSONString(request);
  alipayRequest.setBizContent(bizContent);
  AlipayTradeRefundResponse alipayResponse = alipayClient.execute(alipayRequest);
  RefundResponse response = new RefundResponse();
  response.setResult(alipayResponse.isSuccess());
  response.setCode(alipayResponse.getCode());
  response.setMsg(alipayResponse.getMsg());
  response.setSubCode(alipayResponse.getSubCode());
  response.setSubMsg(alipayResponse.getSubMsg());
  if (alipayResponse.isSuccess()) {
   response.setTradeNo(alipayResponse.getTradeNo());
   response.setOutTradeNo(alipayResponse.getOutTradeNo());
   response.setOpenId(alipayResponse.getOpenId());
   response.setBuyerLoginId(alipayResponse.getBuyerLogonId());
   response.setFundChange(alipayResponse.getFundChange());
   response.setRefundFee(alipayResponse.getRefundFee());
   response.setGmtRefundPay(alipayResponse.getGmtRefundPay());
   response.setStoreName(alipayResponse.getStoreName());
   response.setBuyerUserId(alipayResponse.getBuyerUserId());
  }
  return response;
 }
 
 /**
  * 支付宝对账单查询
  *
  * @param request
  * @return
  * @throws AlipayApiException
  */
 public synchronized QueryBillResponse queryBill(QueryBillRequest request) throws AlipayApiException {
  AlipayClient alipayClient = new DefaultAlipayClient(this.getUrl(), this.getAppid(), this.getRsa_private_key(), this.getFormat(),
   this.getCharset(), this.getAlipay_public_key(), this.getSigntype());
  AlipayDataBillDownloadurlGetRequest alipayRequest = new AlipayDataBillDownloadurlGetRequest();
  alipayRequest.setBillDate(request.getBillDate());
  alipayRequest.setBillType(request.getBillType());
  AlipayDataBillDownloadurlGetResponse alipayResponse = alipayClient.execute(alipayRequest);
  QueryBillResponse response = new QueryBillResponse();
  response.setResult(alipayResponse.isSuccess());
  response.setCode(alipayResponse.getCode());
  response.setMsg(alipayResponse.getMsg());
  response.setSubCode(alipayResponse.getSubCode());
  response.setSubMsg(alipayResponse.getSubMsg());
  if (alipayResponse.isSuccess()) {
   response.setBillDownloadUrl(alipayResponse.getBillDownloadUrl());
  }
  return response;
 }
 
 public String getAppid() {
  return appid;
 }
 
 public void setAppid(String appid) {
  this.appid = appid;
 }
 
 public String getRsa_private_key() {
  return rsa_private_key;
 }
 
 public void setRsa_private_key(String rsa_private_key) {
  this.rsa_private_key = rsa_private_key;
 }
 
 public String getNotify_url() {
  return notify_url;
 }
 
 public void setNotify_url(String notify_url) {
  this.notify_url = notify_url;
 }
 
 public String getReturn_url() {
  return return_url;
 }
 
 public void setReturn_url(String return_url) {
  this.return_url = return_url;
 }
 
 public String getUrl() {
  return url;
 }
 
 public void setUrl(String url) {
  this.url = url;
 }
 
 public String getCharset() {
  return charset;
 }
 
 public void setCharset(String charset) {
  this.charset = charset;
 }
 
 public String getFormat() {
  return format;
 }
 
 public void setFormat(String format) {
  this.format = format;
 }
 
 public String getAlipay_public_key() {
  return alipay_public_key;
 }
 
 public void setAlipay_public_key(String alipay_public_key) {
  this.alipay_public_key = alipay_public_key;
 }
 
 public String getLog_path() {
  return log_path;
 }
 
 public void setLog_path(String log_path) {
  this.log_path = log_path;
 }
 
 public String getSigntype() {
  return signtype;
 }
 
 public void setSigntype(String signtype) {
  this.signtype = signtype;
 }
 
 public String getTimeout_express() {
  return timeout_express;
 }
 
 public void setTimeout_express(String timeout_express) {
  this.timeout_express = timeout_express;
 }
 
 public String getProduct_code() {
  return product_code;
 }
 
 public void setProduct_code(String product_code) {
  this.product_code = product_code;
 }
 
 public String getQrCode_notify_url() {
  return qrCode_notify_url;
 }
 
 public void setQrCode_notify_url(String qrCode_notify_url) {
  this.qrCode_notify_url = qrCode_notify_url;
 }
 
 public String getTimestamp() {
  return timestamp;
 }
 
 public void setTimestamp(String timestamp) {
  this.timestamp = timestamp;
 }

 public String getOffline_notify_url() {
  return offline_notify_url;
 }

 public void setOffline_notify_url(String offline_notify_url) {
  this.offline_notify_url = offline_notify_url;
 }

}
